home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
051-075
/
scopedisk69
/
bval
/
beval.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
7KB
|
375 lines
/* Designed, written and commented by Paul Falstad */
/* This program was extracted from a much, much larger program */
/* by the same author, so don't expect streamlined code. */
extern double Term1(),Parens(),LocalConv(),Term2();
char *Eval(),*FetchSym(),*SkipSpace(),*RetPDB();
main(argc,argv)
int argc;
char **argv;
{
if (argc != 2)
printf("Format: %s (expression)\n",argv[0]);
else
{
printf(Eval(argv[1],0,0L));
printf("\n");
}
}
int isstring(str)
char *str;
{
int isstring = TRUE,parens = 0;
while (*str)
{
if (*str == '(')
parens++;
if (*str == ')')
parens--;
if (parens)
{
str++;
continue;
}
if (*str == '+' || *str == '-' || *str == '*' || *str == '/' ||
*str == '^' || *str == '%' || (*str >= '0' && *str <= '9'))
{
isstring = FALSE;
break;
}
str++;
}
return(isstring);
}
char *Eval(str,rnd,db)
char *str;
int rnd;
double *db;
{
double val = 0;
static char ebuf[512];
while (*str == ' ')
str++;
if (!*str)
return(0);
if (isstring(str))
return(FetchSym(str,0L));
while (*str)
val += Term1(&str);
if (db)
{
*db = val;
return(0L);
}
else
{
DoublePrint(ebuf,val,8);
return(SkipSpace(ebuf));
}
}
double Term1(str)
char **str;
{
char *ptr,buf[80];
long paren = 0;
BOOL first;
if (**str == 0)
return(0);
sprintf(buf,"+%s",*str);
first = TRUE;
for (ptr = buf+1; *ptr; ptr++,(*str)++)
{
if (*ptr == '(')
paren++;
if (*ptr == ')')
paren--;
if (paren)
continue;
if (*ptr == '-' && first)
{
first = FALSE;
continue;
}
first = FALSE;
if (*ptr == '*' || *ptr == '/' || *ptr == '^' || *ptr == '%'
|| *ptr == '^')
{
first = TRUE;
continue;
}
if (*ptr == '+' || *ptr == '-')
break;
}
if (paren)
return(0);
*ptr = NULL;
if (**str == '+')
(*str)++;
return(Term2(buf));
}
double Parens(str)
char *str;
{
char buf[70],*pt;
long parct = 1;
double ret = 0;
sprintf(buf,"%s",str+1);
for (pt = buf; *pt; pt++)
{
if (*pt == '(')
parct++;
if (*pt == ')')
parct--;
if (!parct)
break;
}
if (parct)
return(0);
*pt = NULL;
pt = buf;
while (*pt)
ret += Term1(&pt,&ret);
return(ret);
}
double LocalConv(ch)
char *ch;
{
double val = 0.0,shift = .100;
long mult = 1;
BOOL ped = FALSE;
while (*ch)
{
if (*ch == '.')
{
ped = TRUE;
ch++;
continue;
}
if (*ch == '-' && val == 0 && mult == 1)
{
mult = -1;
ch++;
continue;
}
if (*ch == '*' || *ch == '/' || *ch == '%' || *ch == '^' || *ch == ' ')
break;
if (*ch < '0' || *ch > '9')
return(0);
if (ped)
{
val += shift*(*ch-'0');
shift /= 10;
}
else
val = val*10+(*ch-'0');
ch++;
}
return(val*mult);
}
double Term2(str)
char *str;
{
double a = 0,b;
long paren = 0;
while (*str)
{
if (*(str+1) == '(')
b = Parens(str+1);
else
{
if (tolower(*(str+1)) >= 'a' && tolower(*(str+1)) <= 'z')
FetchSym(str+1,&b);
else
{
if (*(str+1) == '-')
{
if (tolower(*(str+2)) >= 'a' && tolower(*(str+2)) <= 'z')
{
FetchSym(str+2,&b);
b = -b;
}
else
{
if (*(str+2) == '(')
b = -Parens(str+2);
else
b = LocalConv(str+1);
}
}
else
b = LocalConv(str+1);
}
}
switch (*str)
{
case '+':
a = b;
break;
case '*':
a *= b;
break;
case '/':
if (b != 0)
a /= b;
else
a = 0;
break;
case '%':
if (b != 0)
a = (int) a % (int) b;
else
a = 0;
break;
case '^':
a = pow(a,b);
break;
default:
return(0);
};
for (str++; *str; str++)
{
if (*str == '(')
paren++;
if (*str == ')')
{
paren--;
continue;
}
if (paren)
continue;
if (*str == '*' || *str == '/' || *str == '%' || *str == '^')
break;
}
}
return(a);
}
char *FetchSym(str,pdb)
char *str;
double *pdb;
{
char *pt,*tp;
static char stufbuf[80],dobuf[80];
int s0;
double arg;
for (pt = str; *pt; pt++)
if ((tolower(*pt) < 'a' || tolower(*pt) > 'z') &&
(*pt < '0' || *pt > '9') && *pt != '_')
break;
for (tp = stufbuf; str != pt; str++,tp++)
*tp = tolower(*str);
*tp = 0;
if (*pt == '(')
{
if (!strcmp("int",stufbuf))
return(RetPDB((double) ((long) Parens(pt)),pdb));
if (!strcmp("abs",stufbuf))
return(RetPDB(abs(Parens(pt)),pdb));
if (!strcmp("sqrt",stufbuf))
return(RetPDB(sqrt(Parens(pt)),pdb));
if (!strcmp("sin",stufbuf))
return(RetPDB(sin(Parens(pt)/180*PI),pdb));
if (!strcmp("cos",stufbuf))
return(RetPDB(cos(Parens(pt)/180*PI),pdb));
if (!strcmp("tan",stufbuf))
return(RetPDB(tan(Parens(pt)/180*PI),pdb));
if (!strcmp("ln",stufbuf))
{
arg = Parens(pt);
if (arg <= 0)
return(RetPDB((double) 0,pdb));
else
return(RetPDB(log(arg),pdb));
}
if (!strcmp("log",stufbuf))
{
arg = Parens(pt);
if (arg <= 0)
return(RetPDB((double) 0,pdb));
else
return(RetPDB(log10(arg),pdb));
return;
}
if (!strcmp("atan",stufbuf))
return(RetPDB(atan(Parens(pt))/PI*180,pdb));
}
if (!strcmp(stufbuf,"pi"))
{
if (pdb)
{
*pdb = PI;
return;
}
else
return("3.141592654");
}
if (!strcmp(stufbuf,"e"))
{
if (pdb)
{
*pdb = 2.718281828;
return;
}
else
return("2.718281828");
}
}
char *RetPDB(db,dbp)
double db,*dbp;
{
static char pdbuf[512];
if (dbp)
{
*dbp = db;
return(NULL);
}
else
{
DoublePrint(pdbuf,db,8);
return(SkipSpace(pdbuf));
}
}
DoublePrint(buf,val,sigs)
char *buf;
double val;
int sigs;
{
int ptr;
sprintf(buf,"%60.*f",sigs,val);
for (ptr = 59; ptr; ptr--)
{
if (buf[ptr] == '0')
buf[ptr] = 0;
else
break;
}
if (buf[ptr] == '.')
buf[ptr] = 0;
}
char *SkipSpace(ptr)
char *ptr;
{
while (*ptr == ' ')
ptr++;
return(ptr);
}